package com.xquant.pricing.calc.service.impl.otcOption.split;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson2.JSONObject;
import com.xquant.common.core.constant.DictConstant;
import com.xquant.pricing.calc.entity.CalcEngineParam4Simple;
import com.xquant.pricing.calc.entity.simple.LegData;
import com.xquant.pricing.systerm.service.InstrumentService;
import com.xquant.pricing.common.utils.StringUtils;
import com.xquant.pricing.utils.DateUtils;
import com.xquant.pricing.utils.SpringBeanUtils;
import com.xquant.common.engine.xPP.request.CalcEngineParam;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;


/**
 * 功能说明：中泰期权拆分接口
 * 编写作者：xpp
 * 开发日期：2021/11/1 18:43
 * 修改记录：修改日期   修改人    修改内容
 */
public interface CalcCommonService4OtcOptionSplit {


    CalcEngineParam split(CalcEngineParam4Simple sourceCalcEngineParam);

    CalcEngineParam split(CalcEngineParam sourceCalcEngineParam);

    String getSplitCode();

    /**
     * 将000004.SZ转换成系统内可识别的000004,SPT_S,XSHE
     *
     * @return
     */
    default String getInstructionId(String code) {
        String underCode = code;
        //如果有逗号 则视为正常的格式，不需要转换
        if (StringUtils.isNotNull(code) && (!code.contains(",") || code.indexOf(",") == code.length() - 1)) {
            String iCode = code.substring(0, code.indexOf("."));
            String mType = code.substring(code.lastIndexOf(".") + 1, code.length());
            if (mType.contains(",")) {
                mType = mType.substring(0, mType.length() - 1);
            }
            if (DictConstant.EXCHANGE_CODE.CZC.equals(mType)) {
                mType = DictConstant.EXCHANGE_INNER_CODE.CZC;
            } else if (DictConstant.EXCHANGE_CODE.INE.equals(mType)) {
                mType = DictConstant.EXCHANGE_INNER_CODE.INE;
            } else if (DictConstant.EXCHANGE_CODE.DCE.equals(mType)) {
                mType = DictConstant.EXCHANGE_INNER_CODE.DCE;
            } else if (DictConstant.EXCHANGE_CODE.SGE.equals(mType)) {
                mType = DictConstant.EXCHANGE_INNER_CODE.SGE;
            } else if (DictConstant.EXCHANGE_CODE.SH.equals(mType)) {
                mType = DictConstant.EXCHANGE_INNER_CODE.SH;
            } else {
                mType = DictConstant.EXCHANGE_INNER_CODE.SZ;
            }
            //根据内部ICODE和MTYPE去查询标的信息，查询完成后返回逗号分割的内部underCode
            InstrumentService instrumentService = SpringBeanUtils.getBean(InstrumentService.class);
            Map<String, Object> params = new WeakHashMap<>();
            params.put("iCode", iCode);
            params.put("mType", mType);
            List<Map<String, Object>> resultList = instrumentService.getInstruments(params);
            if (resultList.size() > 0) {
                underCode = resultList.get(0).get("code").toString();
            }
        }
        return underCode;

    }

    /**
     * 计息基准转换  A/365转换成Actual/365 TODO
     *
     * @param instBasec 计息基准 客户传入时 A/365
     * @param ifAnnual  是否年化 0-否 1-是
     * @return
     */
    default String transferBasic(String instBasec, String ifAnnual) {
        //如果年化时，为空默认填写 Actual/365
        if (DictConstant.YES_NO.YES.equals(ifAnnual)) {
            if (StringUtils.isNull(instBasec)) {
                instBasec = "Actual/365";
            } else if (instBasec.contains("Actual")) {

            } else {
                instBasec = instBasec.replace("A", "Actual");
            }
        } else {
            instBasec = "Actual/365";
        }

        return instBasec;

    }

    /**
     * 根据传入的简化legData 生成现金借贷JSON
     *
     * @param legData legData简化的条款信息
     * @param rate    费率
     * @return
     */
    default JSONObject getIRSteamObj(LegData legData, String rate) {
        JSONObject streamObj = new JSONObject();
        JSONObject feeObj = new JSONObject();
        //根据期权费生成现金借贷
        feeObj.put("participationRate", (String) legData.getParticipationRate());
        feeObj.put("productType", DictConstant.PRODUCT_TYPE.IRSTREAMS);
        streamObj.put("startDate", legData.getEffectiveDate());
        streamObj.put("startDateConv", "Unadjusted");
        streamObj.put("endDate", legData.getTerminationDate());
        streamObj.put("endDateConv", "Unadjusted");
        streamObj.put("endDateCalendar", "CHINA_EX");
        streamObj.put("dateRegular", "CalculationInPaymentPeriod");
        streamObj.put("calcPeriodFreq", "0D");
        streamObj.put("calcConv", "Following");
        streamObj.put("calcCalendar", "CHINA_EX");
        streamObj.put("calcStubPeriodType", "ShortFinal");
        streamObj.put("calcRollConvention", "NONE");
        streamObj.put("isAccrualByPayment", "1");
        streamObj.put("isPayAtMaturity", "1");
        streamObj.put("firstPaymentDate", "");
        streamObj.put("lastRegularPaymentDate", "");
        streamObj.put("paymentFreq", "0D");
        streamObj.put("paymentConv", "Following");
        streamObj.put("paymentCalendar", "CHINA_EX");
        streamObj.put("paymentRelativeTo", "CalculationPeriodEndDate");
        streamObj.put("paymentDaysOffset", (String) legData.getSettlementDateOffset() + "D");
        streamObj.put("paymentStubPeriodType", "");
        streamObj.put("moneynessOption", legData.getIfAnnual());
        streamObj.put("daycounter", transferBasic(legData.getDayCounter(), legData.getIfAnnual()));
        streamObj.put("paymentRollConvention", "NONE");
        streamObj.put("zeroInterestProtected", "0");
        JSONObject tmpObj = new JSONObject();
        tmpObj.put("initValue", legData.getNotional());
        streamObj.put("notionals", tmpObj);
        JSONObject tmpObj2 = new JSONObject();
        tmpObj2.put("initValue", rate);
        streamObj.put("coupons", tmpObj2);
        feeObj.put("regularIRStream", streamObj);
        return feeObj;
    }

    /***
     * 时间戳转日期
     */
    default String parseCalcDateStr(String timeStr) {
        String format = DateUtil.today();
        DateTime parse = DateUtil.parse(timeStr, "yyyyMMdd HH:mm:ss");
        format = DateUtil.format(parse, "yyyy-MM-dd");

        return format;
    }

    default String getCalcDate(CalcEngineParam4Simple sourceCalcEngineParam) {
        if (null == sourceCalcEngineParam.getHeader() || sourceCalcEngineParam.getHeader().getTimestmp() == null) {
            return DateUtils.getCurr_YYYY_MM_DD();
        }
        return parseCalcDateStr(sourceCalcEngineParam.getHeader().getTimestmp());
    }

    /**
     * 计算年化系数
     *
     * @param calcDate 计算日期
     * @param begDate  开始日期
     * @param endDate  结束日期
     * @param dayCount 计息方式
     * @return
     */
    default BigDecimal getAnnualRatio(String calcDate, String begDate, String endDate, String dayCount) {
        long term = DateUtil.betweenDay(DateUtil.parseDate(begDate), DateUtil.parseDate(endDate), true);
        //365F 时需要判断是否闰年
        Integer daycouterDays = 365;
        if (dayCount.contains("F")) {
            daycouterDays = DateUtil.isLeapYear(Integer.parseInt(calcDate.substring(0, 4))) ? 366 : 365;
        } else {
            String regEx = "\\D+";
            daycouterDays = Integer.parseInt(dayCount.replaceAll(regEx, "").trim());
        }
        //天数默认加一天
        return NumberUtil.div(BigDecimal.valueOf(term), daycouterDays, 20);
    }
}
